package edu.uw.cs.cse461.sp12.OS;

import java.util.ArrayList;
import java.util.List;

import edu.uw.cs.cse461.sp12.OS.DDNSException.DDNSZoneException;
import edu.uw.cs.cse461.sp12.util.Log;

public class DDNSFullName {
	private static final String TAG = "DDNSFullName";
	
	private static final String ROOT_NAME = ".";
	
	private String[] parts;
	private String name;
	
	public DDNSFullName(String name) {
		this.name = name;
		this.parts = name.split("[.]");
		
		if (!this.name.endsWith(".")) {
			this.name += ".";
		}
	}
	
	public String getName() {
		return this.name;
	}
	
	public boolean containsRoot(DDNSFullName root) {
		if (!root.name.equals(ROOT_NAME)) {
			for(int i = 0; i < root.parts.length; i++) {
				if (i >= this.parts.length ||
					!this.parts[this.parts.length - i - 1].equals(root.parts[root.parts.length - i - 1])) {
					// One of the parts in root is not correct.  Return false
					return false;
				}
			}
		}
		// All check succeeded.  Return true
		return true;
	}
	
	public List<DDNSFullName> getSubDomains() {
		List<DDNSFullName> result = new ArrayList<DDNSFullName>();
		
		try {
			String newName = "";
			for(String parts : this.fromRoot(new DDNSFullName(ROOT_NAME))) {
				newName = parts + "." + newName;
				result.add(new DDNSFullName(newName));
			}
		} catch (DDNSZoneException e) {
			// Shouldn't happen.  Log it just in case
			Log.d(TAG, "Unexpected error (getSubDomains): " + e.getMessage());
		}
		
		return result;
	}
	
	public DDNSFullName replace(DDNSFullName origRoot, DDNSFullName newRoot) throws DDNSZoneException {
		String newName = newRoot.name.substring(0, newRoot.name.length() - 1);
		
		for(String parts : this.fromRoot(origRoot)) {
			newName = parts + "." + newName;
		}
		
		return new DDNSFullName(newName);
	}
	
	public List<String> fromRoot(DDNSFullName root) throws DDNSZoneException {
		List<String> result = new ArrayList<String>();
		
		// Check that in the correct zone (this object actually has the given root)
		if (!this.containsRoot(root)) {
			// Invalid root
			throw new DDNSZoneException(root.name, this.toString() + " does not have a root in " + root.toString());
		}
		
		for (int i = this.parts.length - root.parts.length - 1; i >= 0; i--) {
			result.add(this.parts[i]);
		}
		
		return result;
	}
	
	public String getAddressName() {
		return this.parts[0];
	}
	
	@Override
	public int hashCode() {
		return this.name.hashCode();
	}

	@Override
	public boolean equals(Object other) {
		if (other instanceof DDNSFullName) {
			DDNSFullName otherName = (DDNSFullName) other;
			return this.name.equals(otherName.name);
		} else {
			return false;
		}
	}
	
	@Override
	public String toString() {
		return this.name;
	}
}
